
Celem projektu jest porównanie w zależności od problemu(regresja/klasyfikacja) różnego rodzaju modeli wraz z różnego rodzaju hiperparametrami.
● https://www.kaggle.com/uciml/red-wine-quality-cortez-et-al-2009
Team members:
# Libraries for exploring, handling and visualizing data
import pandas as pd, numpy as np, matplotlib.pyplot as plt, seaborn as sns, plotly.express as px
import math
import sklearn
import sklearn.datasets as datasets
from sklearn.preprocessing import OneHotEncoder, StandardScaler, MinMaxScaler, LabelEncoder # Sklearn's preprocessing library
from sklearn.linear_model import LinearRegression
from sklearn.linear_model import LogisticRegression
from sklearn import preprocessing
import sklearn.metrics
import sklearn.model_selection
import sklearn.tree as tree # DRZEWO DECYZYJNE
from scipy import stats
from sklearn.model_selection import cross_validate, GridSearchCV ,RandomizedSearchCV # DO WALIDACJI SKROŚNEJ(KRZYŻOWEJ)
from sklearn.model_selection import train_test_split,cross_val_score, GridSearchCV # Importing train and test data split
from sklearn.tree import DecisionTreeRegressor, DecisionTreeClassifier, plot_tree # DRZEWO DECYZYJNE
import matplotlib.pyplot as plt
%matplotlib inline
import xgboost as xgb
from sklearn.linear_model import LinearRegression
# Sklearn's metrics to evaluate our models
from sklearn.metrics import accuracy_score, precision_score, confusion_matrix, recall_score, f1_score, roc_auc_score,classification_report, mean_squared_error, plot_roc_curve
from sklearn import metrics, tree
from sklearn.ensemble import RandomForestClassifier, VotingClassifier, GradientBoostingClassifier, AdaBoostClassifier # Classifiers
from sklearn.linear_model import LogisticRegression # estymator klasyfikacji=klasyfikator
from mlxtend import plotting
# Setting theme style and color palette to seaborn
sns.set_theme(context = 'notebook', style='darkgrid',palette='muted')
from mlxtend.plotting import plot_decision_regions
from sklearn.svm import SVC, SVR
from IPython.display import Image
from sklearn.multiclass import OneVsRestClassifier
from sklearn.datasets import fetch_california_housing
from yellowbrick.model_selection import FeatureImportances
import statsmodels.api as sm
from sklearn.decomposition import PCA # analiza głównych składowych - w celu redukcji wymiarowości danych
from scipy import signal
import scipy
from imblearn.over_sampling import SMOTE
from sklearn.metrics import RocCurveDisplay
from sklearn.metrics import fbeta_score, make_scorer
from time import time
import scikitplot as skplt
import graphviz.backend as be
from dtreeviz.trees import *
import warnings
warnings.filterwarnings('ignore')
Zbiór zawiera 1599 wierszy i 11 kolumn. Zmienną wynikową jest quality.
%cd "C:\Users\tk\Desktop\ratunek code\jdszr7-code-breakers\projekt_ML"
wine = pd.read_csv("winequality-red.csv")
wine # display the data frame
wine.head(11)
C:\Users\tk\Desktop\ratunek code\jdszr7-code-breakers\projekt_ML
| fixed acidity | volatile acidity | citric acid | residual sugar | chlorides | free sulfur dioxide | total sulfur dioxide | density | pH | sulphates | alcohol | quality | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | 7.4 | 0.70 | 0.00 | 1.9 | 0.076 | 11.0 | 34.0 | 0.9978 | 3.51 | 0.56 | 9.4 | 5 |
| 1 | 7.8 | 0.88 | 0.00 | 2.6 | 0.098 | 25.0 | 67.0 | 0.9968 | 3.20 | 0.68 | 9.8 | 5 |
| 2 | 7.8 | 0.76 | 0.04 | 2.3 | 0.092 | 15.0 | 54.0 | 0.9970 | 3.26 | 0.65 | 9.8 | 5 |
| 3 | 11.2 | 0.28 | 0.56 | 1.9 | 0.075 | 17.0 | 60.0 | 0.9980 | 3.16 | 0.58 | 9.8 | 6 |
| 4 | 7.4 | 0.70 | 0.00 | 1.9 | 0.076 | 11.0 | 34.0 | 0.9978 | 3.51 | 0.56 | 9.4 | 5 |
| 5 | 7.4 | 0.66 | 0.00 | 1.8 | 0.075 | 13.0 | 40.0 | 0.9978 | 3.51 | 0.56 | 9.4 | 5 |
| 6 | 7.9 | 0.60 | 0.06 | 1.6 | 0.069 | 15.0 | 59.0 | 0.9964 | 3.30 | 0.46 | 9.4 | 5 |
| 7 | 7.3 | 0.65 | 0.00 | 1.2 | 0.065 | 15.0 | 21.0 | 0.9946 | 3.39 | 0.47 | 10.0 | 7 |
| 8 | 7.8 | 0.58 | 0.02 | 2.0 | 0.073 | 9.0 | 18.0 | 0.9968 | 3.36 | 0.57 | 9.5 | 7 |
| 9 | 7.5 | 0.50 | 0.36 | 6.1 | 0.071 | 17.0 | 102.0 | 0.9978 | 3.35 | 0.80 | 10.5 | 5 |
| 10 | 6.7 | 0.58 | 0.08 | 1.8 | 0.097 | 15.0 | 65.0 | 0.9959 | 3.28 | 0.54 | 9.2 | 5 |
def pairplot():
sns.pairplot(wine, hue="quality")
plt.suptitle('Wykresy - rozkład zmiennych', y=1.03, fontsize=18, fontweight='semibold');
pairplot();
def wykresy_pudelkowe():
wine.plot(kind= 'box',
subplots=True,
layout=(4,4),
figsize=(15,12)),
plt.suptitle('Wykresy - rozkład zmiennych', y=1.03, fontsize=18, fontweight='semibold');
wykresy_pudelkowe();
def wykresy_zmienne():
for i in wine.columns[:-1]:
plt.figure()
sns.barplot(x=wine.quality, y=wine[i])
plt.plot()
wykresy_zmienne();
def wykresy_zmienne_1():
for i in wine.columns[:-1]:
plt.figure()
sns.boxplot(x=wine.quality, y=wine[i])
plt.plot()
wykresy_zmienne_1()
def analiza_korelacji():
f,ax = plt.subplots(figsize=(13,10))
mask = np.triu(np.ones_like(wine.corr(method='spearman')), k=0)
sns.set(font_scale=1)
sns.heatmap(wine.corr(method='spearman'), annot=True, linewidths=1, fmt='.2f', ax=ax, cmap="turbo", annot_kws={'fontsize':12}, mask=mask)
plt.suptitle('Analiza korelacji', y=1.03, fontsize=18, fontweight='semibold');
analiza_korelacji()
#### Analiza duplikatów Zbiór zawiera 240 zduplikowanych wartości. Ponieważ nie ma informacji o tym, jak pobrano próbki zestawu danych, zakładamy, że mamy do czynienia z drugim przypadkiem i dlatego zachowujemy duplikaty.
#### Analiza brakujących wartości Zbiór nie zawiera brakującyh wartości
#### Na podstawie wstępnej analizy danych do modelu zostało wybranych 7 zmiennych:
volatile acidity, citric acid,total sulfur dioxide, density, sulphates, alcohol, quality.
#### Usuwamy outliery
Zbiór zawiera 240 zduplikowanych wartości. Ponieważ nie ma informacji o tym, jak pobrano próbki zestawu danych, zakładamy, że mamy do czynienia z drugim przypadkiem i dlatego zachowujemy duplikaty.
#Analiza duplikatów
wine.duplicated().sum()
240
Zbiór nie zawiera brakującyh wartości
wine.isnull().sum()
#Zbiór nie zawiera braków danych.
fixed acidity 0 volatile acidity 0 citric acid 0 residual sugar 0 chlorides 0 free sulfur dioxide 0 total sulfur dioxide 0 density 0 pH 0 sulphates 0 alcohol 0 quality 0 dtype: int64
volatile acidity, citric acid,total sulfur dioxide, density, sulphates, alcohol,quality
wine.drop(['fixed acidity','residual sugar','chlorides','free sulfur dioxide','pH'], axis=1, inplace=True)
wine.head()
| volatile acidity | citric acid | total sulfur dioxide | density | sulphates | alcohol | quality | |
|---|---|---|---|---|---|---|---|
| 0 | 0.70 | 0.00 | 34.0 | 0.9978 | 0.56 | 9.4 | 5 |
| 1 | 0.88 | 0.00 | 67.0 | 0.9968 | 0.68 | 9.8 | 5 |
| 2 | 0.76 | 0.04 | 54.0 | 0.9970 | 0.65 | 9.8 | 5 |
| 3 | 0.28 | 0.56 | 60.0 | 0.9980 | 0.58 | 9.8 | 6 |
| 4 | 0.70 | 0.00 | 34.0 | 0.9978 | 0.56 | 9.4 | 5 |
# funkcja zwracająca cechy numeryczne
def get_quant_features(wine):
feats = wine.select_dtypes([np.number, np.bool]).columns
return [x for x in feats]
# funkcja rysująca histogramy dla numerycznych cechy
def draw_histograms(wine, variables, n_rows, n_cols):
fig=plt.figure(figsize=(16,10))
for i, var_name in enumerate(variables):
ax=fig.add_subplot(n_rows,n_cols,i+1)
wine[var_name].hist(bins=20,ax=ax)
ax.set_title(var_name)
fig.tight_layout()
plt.show()
def wykres_feats():
feats = get_quant_features(wine)
draw_histograms(wine, feats, 2, 4) # dwa wiersze i cztery kolumny
plt.suptitle('Rozkład wybranych zmiennych', y=1.03, fontsize=18, fontweight='semibold');
wykres_feats();
<Figure size 432x288 with 0 Axes>
columns = ['volatile acidity', 'citric acid',
'total sulfur dioxide', 'density',
'sulphates', 'alcohol','quality']
def rm_out(wine):
df_out = wine.copy()
means, stdevs = {}, {}
for column in df_out.columns:
means[column] = df_out[column].mean()
stdevs[column] = df_out[column].std()
for column in df_out.columns:
lower = means[column] - 3 * stdevs[column]
upper = means[column] + 3 * stdevs[column]
index = (lower < df_out[column]) & (df_out[column] < upper)
df_out = df_out[index]
df_out.index = range(len(df_out))
return df_out
df= rm_out(wine[columns])
df["quality"].value_counts()
5 643 6 616 7 192 4 49 8 16 Name: quality, dtype: int64
Zbiór danych ma znacznie większą liczbę wartości 0, co wskazuje, że dane zawierają więcej wierszy, które reprezentują złą jakość wina. Zbiór jest mocno niezbalansowany.
df["quality"] = df["quality"].astype(object)
bins = [2, 6.5, 8]
values = ["bad", "good"]
df["quality"] = pd.cut(df["quality"], bins=bins, labels= values)
df["quality"].unique()
['bad', 'good'] Categories (2, object): ['bad' < 'good']
label_qlt = LabelEncoder()
df["quality"] = label_qlt.fit_transform(df["quality"])
df["quality"].value_counts()
0 1308 1 208 Name: quality, dtype: int64
def wykres_quality():
sns.countplot(x ="quality", data = df)
plt.show()
plt.suptitle('Rozkład zmiennej wynikowej', y=1.03, fontsize=18, fontweight='semibold');
wykres_quality();
<Figure size 432x288 with 0 Axes>
X = df.drop("quality", axis=1)
y = df["quality"]
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=.2, stratify = df.quality, random_state=42)
print("The shape of X_train is:",X_train.shape)
print("The shape of X_test is:",X_test.shape)
print("The shape of y_train is:",y_train.shape)
print("The shape of y_test is:",y_test.shape)
The shape of X_train is: (1212, 6) The shape of X_test is: (304, 6) The shape of y_train is: (1212,) The shape of y_test is: (304,)
Do niektórych modeli dane muszą być znormalizowane.
W tym celu tworzymy kopię danych, które poddajemy standaryzacji.
Model drzewa decyzyjnego i lasu losowego budowany jest na danych niestandaryzwoanych.
Ponieważ zbiór jest mocno niezrónoważony stosujemy oversampling - metody SMOTE.
scaler = StandardScaler().fit(X_train)
X_train_scal = scaler.transform(X_train)
X_test_scal = scaler.transform(X_test)
def wykres_plotting():
from mlxtend.plotting import scatterplotmatrix
cols = ['volatile acidity', 'citric acid',
'total sulfur dioxide', 'density',
'sulphates', 'alcohol']
scatterplotmatrix(df[cols].values, figsize=(20, 28),names=cols, alpha=0.5)
plt.tight_layout()
plt.show()
plt.suptitle('Wykresy - rozkład zmiennych', y=1.03, fontsize=18, fontweight='semibold');
# macierz wykresów stanowi przydatne graficzne pods występujących w zbiorze danych.
wykres_plotting();
<Figure size 432x288 with 0 Axes>
def wykres_rownolegly():
# Wykres współrzędnych równoległych Dla danych wielowymiarowych
from pandas.plotting import ( parallel_coordinates,)
fig, ax = plt.subplots (figsize=(21, 4))
new_df = X.copy()
new_df["target"] = y
parallel_coordinates(new_df, "target", ax=ax,colormap="viridis", alpha=0.5,)
ax.set_xticklabels ( ax.get_xticklabels(), rotation=45)
ax.set_title("Współrzędne równoległe 6 cech")
wykres_rownolegly()
def wykres_odrebnosci_cech():
# Wykres ma postać koła w którego wnętrzu znajdują się punkty reprezentujące próbki danych a na obrzeżach cechy. Wartości są znormalizowane. Każdy punkt jest połączony za pomocą sprężyny z cechami do których jest przyciągany.
# Jest to jeden ze sposobów wizualizowanie odrębności cech
from pandas.plotting import radviz
fig, ax = plt.subplots (figsize=(16, 16))
new_df = X.copy()
new_df ["target"] = y
radviz(new_df, "target", ax=ax, colormap="PiYG")
ax.set_title("Wykres RadViz 8 cech")
wykres_odrebnosci_cech()
Ponieważ zmienna wynikowa po przekształceniu przyjmuje wartości 0 lub 1 wybraliśmy następujące modele:
Modele te zostały wybrane, żeby móc odpowiedzieć na następujące pytania:
Stworzyliśmy również model K-Means.
- Recall
- Precision
- F1
- AUC
model_LR=LogisticRegression().fit(X_train_scal,y_train)
##współczynniki - beta mówią o ważności zmiennych, jak dany czynnik wpływa na prawdopodobieństwo.
model_LR.coef_
array([[-0.45049787, 0.07000906, -0.5762978 , -0.00972262, 0.72285445,
1.05574208]])
X_train.columns
Index(['volatile acidity', 'citric acid', 'total sulfur dioxide', 'density',
'sulphates', 'alcohol'],
dtype='object')
pred_test=model_LR.predict(X_test_scal)
#Ocena jakości modelu
score = model_LR.score(X_test_scal,y_test)
print("The score is {}".format(score))
prec = precision_score(y_test, pred_test)
print("The precision is {}".format(prec))
rec = recall_score(y_test, pred_test)
print("The recall is {}".format(rec))
f1 = f1_score(y_test, pred_test)
print("The F1-Score is {}".format(f1))
The score is 0.9046052631578947 The precision is 0.6756756756756757 The recall is 0.5952380952380952 The F1-Score is 0.6329113924050633
print(classification_report(y_test, pred_test,target_names=["słabe", "dobre"]))
precision recall f1-score support
słabe 0.94 0.95 0.95 262
dobre 0.68 0.60 0.63 42
accuracy 0.90 304
macro avg 0.81 0.77 0.79 304
weighted avg 0.90 0.90 0.90 304
def confusion_matrix_LR():
LABELS = ['słabe', 'dobre']
conf_matrix = confusion_matrix(y_test, pred_test)
plt.figure(figsize =(5, 5))
sns.heatmap(conf_matrix, xticklabels = LABELS,
yticklabels = LABELS, annot = True, fmt ="d");
plt.title("Confusion matrix")
plt.ylabel('True class')
plt.xlabel('Predicted class')
plt.show()
confusion_matrix_LR()
RocCurveDisplay.from_estimator(model_LR, X_test_scal, y_test);
# Predicting Cross Validation Score
cv=cross_val_score(model_LR, X_train_scal, y_train, cv=10).mean()
print("Cross Validation Score : ", cv)
Cross Validation Score : 0.8754098360655738
params = {'C': [0.001,0.01,0.1,1,10],'solver': ['newton-cg', 'lbfgs', 'liblinear', 'sag', 'saga']}
grid_search = GridSearchCV(LogisticRegression(penalty='l2'), param_grid=params,scoring='recall',cv=5)
grid_search.fit(X_train_scal, y_train)
GridSearchCV(cv=5, estimator=LogisticRegression(),
param_grid={'C': [0.001, 0.01, 0.1, 1, 10],
'solver': ['newton-cg', 'lbfgs', 'liblinear', 'sag',
'saga']},
scoring='recall')In a Jupyter environment, please rerun this cell to show the HTML representation or trust the notebook. GridSearchCV(cv=5, estimator=LogisticRegression(),
param_grid={'C': [0.001, 0.01, 0.1, 1, 10],
'solver': ['newton-cg', 'lbfgs', 'liblinear', 'sag',
'saga']},
scoring='recall')LogisticRegression()
LogisticRegression()
print(grid_search.best_score_)
print(grid_search.score(X = X_test_scal, y = y_test))
print(grid_search.best_params_)
0.39732620320855616
0.6428571428571429
{'C': 0.001, 'solver': 'liblinear'}
#Create an object (model)
dt = DecisionTreeClassifier(
random_state=42,
max_depth=5,
class_weight=None,
criterion='gini',
max_features=None,
max_leaf_nodes=None,
min_impurity_decrease=0.0,
min_samples_leaf=2,
min_weight_fraction_leaf=0.0,
splitter='best')
dt.fit(X_train, y_train)
dt.score (X_test, y_test)
0.8881578947368421
dt.predict_proba (X.iloc[[0]])
array([[1., 0.]])
# Walidacja
cv_results = cross_val_score(dt,X, y,cv=5) #ilokrotność walidacji cv(razy: trening na 4, testowanie na jednej | dzięki wielu podziałom można zobczyć jak radzi sobie z danymi
print(f'Scores: {np.round(cv_results,3)}')
Scores: [0.872 0.802 0.894 0.818 0.861]
print(f'Scores mean: {np.round(np.mean(cv_results),3)}') #liczę średnią ze scorów z kroswalidacji, wynik zbliżony z wynikiem score
Scores mean: 0.85
# 5 sprawdzamy dokładność, w regresji było accuracy, tutaj score
dt.score( X_test,y_test) # wartość r2, kroswalidacja robi pięciokrotne taka czynność na 4 treningowych | SCORE Z DANYCH I TARGETU , MODEL JEST FITOWANY DO TYCH DANYCH
#powinno być powyżej 0,9, score jest właściwy dla danych zbalansowanych
0.8881578947368421
# Poniżej przedstawiony jest kod wizualizujący ważności cech Giniego (dzięki nim można zmniejszyć błąd modelu):
for col, val in sorted(zip (X.columns, dt.feature_importances_),
key=lambda x: x[1], reverse=True,
)[:5]:
print(f" {col:10} {val: 10.3f}")
alcohol 0.422 sulphates 0.282 total sulfur dioxide 0.113 volatile acidity 0.105 citric acid 0.063
def wykres_waznosci_Cech_drzewo():
# Wykres ważności cech w odniesieniu do największej bezwzględnej wartości współczynnika regresji. Użyta do tej funkcja wizualizuj sama argument relative= True który powoduje że największej wartość jest przypisywana liczba
# 100 lub minus 100 a pozostałem wartością proporcjonalnie mniejsze liczby.
from yellowbrick.model_selection import FeatureImportances
fig, ax = plt.subplots (figsize=(6, 4))
fi_viz = FeatureImportances (dt)
fi_viz.fit(X, y)
fi_viz.ax.set(title="Ważność 6 cech (drzewo decyzyjne)", xlabel = "Względna ważność")
wykres_waznosci_Cech_drzewo()
X
| volatile acidity | citric acid | total sulfur dioxide | density | sulphates | alcohol | |
|---|---|---|---|---|---|---|
| 0 | 0.700 | 0.00 | 34.0 | 0.99780 | 0.56 | 9.4 |
| 1 | 0.880 | 0.00 | 67.0 | 0.99680 | 0.68 | 9.8 |
| 2 | 0.760 | 0.04 | 54.0 | 0.99700 | 0.65 | 9.8 |
| 3 | 0.280 | 0.56 | 60.0 | 0.99800 | 0.58 | 9.8 |
| 4 | 0.700 | 0.00 | 34.0 | 0.99780 | 0.56 | 9.4 |
| ... | ... | ... | ... | ... | ... | ... |
| 1511 | 0.600 | 0.08 | 44.0 | 0.99490 | 0.58 | 10.5 |
| 1512 | 0.550 | 0.10 | 51.0 | 0.99512 | 0.76 | 11.2 |
| 1513 | 0.510 | 0.13 | 40.0 | 0.99574 | 0.75 | 11.0 |
| 1514 | 0.645 | 0.12 | 44.0 | 0.99547 | 0.71 | 10.2 |
| 1515 | 0.310 | 0.47 | 42.0 | 0.99549 | 0.66 | 11.0 |
1516 rows × 6 columns
viz = dtreeviz(dt, X,y,target_name="cel",feature_names=X.columns, class_names=["słabe", "dobre"],scale=(0.8),title="Obraz drzewa z 100 histogramami")
viz
prediction_tr = dt.predict(X_train)
prediction_ts = dt.predict(X_test)
print(sklearn.metrics.classification_report(y_test, prediction_ts, target_names=["słabe", "dobre"]))
precision recall f1-score support
słabe 0.94 0.94 0.94 262
dobre 0.60 0.60 0.60 42
accuracy 0.89 304
macro avg 0.77 0.77 0.77 304
weighted avg 0.89 0.89 0.89 304
print('accuracy train data is',accuracy_score(y_train,prediction_tr))
print('accuracy test data is',accuracy_score(y_test,prediction_ts))
accuracy train data is 0.9158415841584159 accuracy test data is 0.8881578947368421
print('recall train data is',recall_score(y_train,prediction_tr,average="macro"))
print('recall test data is',recall_score(y_test,prediction_ts,average="macro"))
recall train data is 0.7992006265981708 recall test data is 0.7651762995274445
# get confusion matrix
predictions = dt.predict(X_test)
matrix = sklearn.metrics.confusion_matrix(y_test, predictions)
matrix
array([[245, 17],
[ 17, 25]], dtype=int64)
# 9 Użyteczną metryką jest f1_score - średnia harmoniczna precyzji i czułości
# "micro" is preferrable, "macro" is good if there is no class imbalance
sklearn.metrics.f1_score(y_test, predictions, average="micro") #micro -ustala w jaki sposób będziemy uśedniać po klasach
0.8881578947368421
from yellowbrick.classifier import (ConfusionMatrix,)
mapping = {0: "Słabe", 1: "Dobre"}
fig, ax = plt.subplots (figsize=(6, 6))
cm_viz = ConfusionMatrix( dt,classes=["Słabe", "Dobre"], label_encoder=mapping,)
cm_viz.score (X_test, y_test)
cm_viz.ax.set(title="Tablica pomyłek klasyfikatora drzewa ", xlabel="Klasa prognozowana", ylabel="Klasa rzeczywista")
# Ćwiartki lewa górna i prawa dolna zawierają poprawne wyniki klasyfikacji, a lewa dolna i prawa górna -błędne; ćwiartka lewa dolna zawiera wyniki fałszywie negatywne
# a prawa górna - fałszywie pozytywne. Centrum dobrego klasyfikatora są duże wartości prawdziwych wyników na przekątnej tabeli
[Text(0.5, 1.0, 'Tablica pomyłek klasyfikatora drzewa '), Text(0.5, 0, 'Klasa prognozowana'), Text(0, 0.5, 'Klasa rzeczywista')]
from yellowbrick.classifier import (ClassificationReport,)
def drzewo_raport_klasyfikacyjny():
# Raport klasyfikacyjny prezentujący precyzję, czułośc, wskaźnik F1 dla wyników pozytywnych i negatywnych.
# Im dany wskaźnik jest lepszy -bliższy jedności -tym komórka jest bardziej czerwona
fig, ax = plt.subplots (figsize=(6, 3))
cm_viz = ClassificationReport( dt,classes=["SŁABE", "DOBRE"], label_encoder=mapping)
cm_viz.score (X_test, y_test)
cm_viz.ax.set (title="Raport klasyfikacyjny drzewa losowego")
xlabels = ("Precyzja", "Czułość", "F1")
ax.set_xticks (np.arange(len(xlabels)) + 0.5)
ax.set_xticklabels (xlabels, rotation=45)
ax.set_yticks (np.arange(len(cm_viz.classes)) + 0.5)
ax.set_yticklabels (cm_viz.classes)
drzewo_raport_klasyfikacyjny()
Jeżeli klasy nie są zrównoważone wtedy na podstawie krzywej ROC można wyciągnąć nadmiernie optymistyczne wnioski. Dlatego stosowany jest inny sposób oceniania klasyfikatora polegające na wykreśleniu krzywej Precision- Recall curve. Klasyfikacja to zrównoważony proces wyszukiwania potrzebnych danych (czułość) przy jednoczesnym ograniczeniu błędnych wyników (precyzja). Zazwyczaj trzeba znaleźć kompromis między tymi pojęciami. Im większa czułość tym mniejsza precyzja i odwrotnie.
def prezycja_czulosc_drzewo():
from yellowbrick.classifier import ( PrecisionRecallCurve,)
fig, ax = plt.subplots (figsize=(6, 4))
viz = PrecisionRecallCurve (DecisionTreeClassifier (max_depth=3))
viz. fit (X_train, y_train)
print(viz.score (X_test, y_test))
viz.ax.set(title="Krzywa precyzja-czułość klasyfikatora drzewa",xlabel="Czułość", ylabel="Precyzja")
ax.legend (("Binarna krzywa precyzja-czułość","Średnia precyzja = {:0.2f}".format (viz.score(X_test,y_test))),frameon=True, loc="lower left")
prezycja_czulosc_drzewo()
0.5077767514532168
def wykres_rownowaga_klas_drzewo():
# Równowaga class
# Wykres ilustruje wielkość klas, jeżeli klasy różnią się wielkością wtedy dokładność nie jest odpowiednim wskaźnikiem jakości modelu.
# Aby zachować właściwe proporcje między klasami danych należy przydzieleniu ich na zbiory treningowy i testowy stosować losowanie warstwowe (parametr stratify)
from yellowbrick.classifier import ClassBalance
fig, ax = plt.subplots (figsize=(6,6))
cb_viz=ClassBalance (labels =["Słabsze", "Lepsze"])
cb_viz.fit(y_test)
ax.set_xticks (np.arange(len(cb_viz.labels)))
ax.set_xticklabels (cb_viz.labels)
ax.set(title="Równowaga klas dla (:,) próbek".format(cb_viz.support_.sum()), ylabel="Liczba próbek")
# Na wykresie uzyskano nierównowagę klas
wykres_rownowaga_klas_drzewo()
def wykres_blad_prognozowania_klas():
# Błąd prognozowania klas
# wykres błędu prognozowania klas ilustrujący tablicę pomyłek.
from yellowbrick.classifier import (ClassPredictionError,)
fig, ax = plt.subplots (figsize=(6, 3))
cpe_viz = ClassPredictionError(dt, classes=["Słabsze", "Lepsze"])
cpe_viz.score (X_test, y_test)
ax.set_xticks (np.arange(len(cpe_viz.classes)))
ax.set_xticklabels (cpe_viz.classes)
ax.set(title="Błąd prognozowania klas dla klasyfikatora drzewa losowego", xlabel="Klasa rzeczywista", ylabel="Klasa prognozowana")
wykres_blad_prognozowania_klas()
def wykres_analiza_lime_drzewo():
# Analiza LIME pokazująca, jak poszczególne cechy próbki przesuwają wyniki prognozy w prawo (wybór lepszego gatunku) lub w lewo (słabego gatunku)
# Poniżej przedstawiony jest kod umożliwiający interpretację ostatniej próbki danych ze zbioru treningowego, dla której nasz model drzewa decyzyjnego prognozuje wybór lepszego gatunku:
from lime import lime_tabular
explainer = lime_tabular. LimeTabularExplainer(X_train.values, feature_names=X.columns, class_names=["słabsze", "lepsze"])
exp = explainer.explain_instance( X_train.iloc[-1].values, dt.predict_proba)
# Danymi wejściowymi dla pakietu LIME nie może być struktura DataFrame. Zwróć uwagę, że jest ona zamieniana na tablicę numpy za pomocą atrybutu .values.
fig = exp.as_pyplot_figure()
fig.tight_layout()
fig.gca().set (title="Lokalna interpretacja klasy '%s'" % exp.class_names [1])
wykres_analiza_lime_drzewo()
ypred = dt.predict(X_test)
ypred
roc_auc_score(y_test, ypred)
0.7651762995274446
plot_roc_curve(dt, X_test, y_test)
<sklearn.metrics._plot.roc_curve.RocCurveDisplay at 0x2516d5fe950>
def lin_regplot(X,y,model):
plt.scatter(X,y,c='steelblue',edgecolor ='white', s = 70)
plt.plot(X, model.predict(X),color='black', lw=2)
return None
def wykres_regresji_przy_uzyciu_drzewa():
# Wykres regresji przy użyciu drzewa
X_sul=df[['sulphates']].values
y_q=df['alcohol'].values
tree = DecisionTreeRegressor(max_depth=3)
tree.fit(X_sul, y_q)
sort_idx= X_sul. flatten().argsort()
lin_regplot (X_sul[sort_idx], y_q[sort_idx], tree)
plt.xlabel('Nieliniowy związek zmiennych [sulphates i alkohol]-trend kształtujący dane')
plt.ylabel('Zawartość alkoholu')
wykres_regresji_przy_uzyciu_drzewa()
#Tworzę pierwszy model
rfc=RandomForestClassifier(criterion='gini',n_estimators=100,random_state=42,bootstrap=True,max_depth=None,min_samples_split=2)
rfc.fit(X_train, y_train)
yPred=rfc.predict(X_train)
yPred_test=rfc.predict(X_test)
#Ocena jakości modelu
score = rfc.score(X_test,y_test)
print("The score is {}".format(score))
prec = precision_score(y_test, yPred_test)
print("The precision is {}".format(prec))
rec = recall_score(y_test, yPred_test)
print("The recall is {}".format(rec))
f1 = f1_score(y_test, yPred_test)
print("The F1-Score is {}".format(f1))
The score is 0.9144736842105263 The precision is 0.7105263157894737 The recall is 0.6428571428571429 The F1-Score is 0.6749999999999999
CR_model1=classification_report( y_test,yPred_test,target_names=["słabe", "dobre"])
print(CR_model1)
precision recall f1-score support
słabe 0.94 0.96 0.95 262
dobre 0.71 0.64 0.67 42
accuracy 0.91 304
macro avg 0.83 0.80 0.81 304
weighted avg 0.91 0.91 0.91 304
#Confusion Matrix
LABELS = ['słabe', 'dobre']
conf_matrix = confusion_matrix(y_test, yPred_test)
plt.figure(figsize =(5, 5))
sns.heatmap(conf_matrix, xticklabels = LABELS,
yticklabels = LABELS, annot = True, fmt ="d");
plt.title("Confusion matrix")
plt.ylabel('True class')
plt.xlabel('Predicted class')
plt.show()
def raport_las():
# Raport klasyfikacyjny prezentujący precyzję, czułośc, wskaźnik F1 dla wyników pozytywnych i negatywnych.
# Im dany wskaźnik jest lepszy -bliższy jedności -tym komórka jest bardziej czerwona
from yellowbrick.classifier import (ClassificationReport,)
fig, ax = plt.subplots (figsize=(6, 3))
cm_viz = ClassificationReport( rfc,classes=["SŁABE", "DOBRE"], label_encoder=mapping)
cm_viz.score (X_test, y_test)
cm_viz.ax.set (title="Raport klasyfikacyjny lasu losowego")
xlabels = ("Precyzja", "Czułość", "F1")
ax.set_xticks (np.arange(len(xlabels)) + 0.5)
ax.set_xticklabels (xlabels, rotation=45)
ax.set_yticks (np.arange(len(cm_viz.classes)) + 0.5)
ax.set_yticklabels (cm_viz.classes)
raport_las()
#ROC_RF = plot_roc_curve(rfc, X_test, y_test)
#plt.show()
RocCurveDisplay.from_estimator(rfc, X_test, y_test);
cv_results=cross_val_score(rfc,X_train,y_train,cv=5)
print(cv_results)
print(f'Scores: {np.round(cv_results,2)}')
print(f'Scores mean: {np.round(np.mean(cv_results),3)}')
[0.89300412 0.90123457 0.90909091 0.90495868 0.89669421] Scores: [0.89 0.9 0.91 0.9 0.9 ] Scores mean: 0.901
params={'criterion': ['gini','entropy'],
'n_estimators': [100,200,50,20],
'max_depth': [2,4,5,10,None],
'min_samples_leaf': [1, 2, 3, 4, 5, 10, 20, 25],
'max_features':['sqrt','log2',None]
}
grid_search_rfc = GridSearchCV(rfc, param_grid=params, cv=5, scoring='recall',n_jobs=-1,verbose=1)
grid_search_rfc.fit(X_train, y_train)
Fitting 5 folds for each of 960 candidates, totalling 4800 fits
GridSearchCV(cv=5, estimator=RandomForestClassifier(random_state=42), n_jobs=-1,
param_grid={'criterion': ['gini', 'entropy'],
'max_depth': [2, 4, 5, 10, None],
'max_features': ['sqrt', 'log2', None],
'min_samples_leaf': [1, 2, 3, 4, 5, 10, 20, 25],
'n_estimators': [100, 200, 50, 20]},
scoring='recall', verbose=1)In a Jupyter environment, please rerun this cell to show the HTML representation or trust the notebook. GridSearchCV(cv=5, estimator=RandomForestClassifier(random_state=42), n_jobs=-1,
param_grid={'criterion': ['gini', 'entropy'],
'max_depth': [2, 4, 5, 10, None],
'max_features': ['sqrt', 'log2', None],
'min_samples_leaf': [1, 2, 3, 4, 5, 10, 20, 25],
'n_estimators': [100, 200, 50, 20]},
scoring='recall', verbose=1)RandomForestClassifier(random_state=42)
RandomForestClassifier(random_state=42)
print(grid_search_rfc.best_score_)
print(grid_search_rfc.score(X = X_test, y = y_test))
print(grid_search_rfc.best_params_)
0.5361853832442067
0.6428571428571429
{'criterion': 'gini', 'max_depth': None, 'max_features': None, 'min_samples_leaf': 1, 'n_estimators': 200}
W celu zrównoważenia danych używam oversamplingu ( metoda SMOTE). Tworzę model z parametrem sampling_strategy=0.75
from imblearn.over_sampling import SMOTE
sm2 = SMOTE(sampling_strategy=0.75,random_state=42)
X_res2, y_res2 = sm2.fit_resample(X_train, y_train)
ax = sns.countplot(x=y_res2)
abs_values = y_res2.value_counts().values
ax.bar_label(container=ax.containers[0], labels=abs_values);
# Buduję model na danych poddanych oversamplingowi.
rfc_over2=RandomForestClassifier(n_estimators=100,random_state=42,bootstrap=True,max_depth=None,min_samples_split=2)
rfc_over2.fit(X_res2, y_res2)
yPred_over2=rfc_over2.predict(X_test)
print(classification_report(y_test, yPred_over2,target_names=["słabe", "dobre"]))
precision recall f1-score support
słabe 0.96 0.90 0.93 262
dobre 0.56 0.79 0.65 42
accuracy 0.88 304
macro avg 0.76 0.84 0.79 304
weighted avg 0.91 0.88 0.89 304
# Ocena jakości modelu
score_over2 = rfc_over2.score(X_test, y_test)
print("The score is {}".format(score_over2))
prec_over_rfc2 = precision_score(y_test, yPred_over2)
print("The precision is {}".format(prec_over_rfc2))
rec_over_rfc2 = recall_score(y_test, yPred_over2)
print("The recall is {}".format(rec_over_rfc2))
f1_over_rfc2 = f1_score(y_test, yPred_over2)
print("The F1-Score is {}".format(f1_over_rfc2))
The score is 0.8848684210526315 The precision is 0.559322033898305 The recall is 0.7857142857142857 The F1-Score is 0.6534653465346535
def confusion_matrix_las_po_oversamplingu():
#Confusion Matrix
LABELS = ['słabe', 'dobre']
conf_matrix = confusion_matrix(y_test, yPred_over2)
plt.figure(figsize =(5, 5))
sns.heatmap(conf_matrix, xticklabels = LABELS,
yticklabels = LABELS, annot = True, fmt ="d");
plt.title("Confusion matrix")
plt.ylabel('True class')
plt.xlabel('Predicted class')
plt.show()
confusion_matrix_las_po_oversamplingu()
def las_po_oversamplingu():
# Raport klasyfikacyjny prezentujący precyzję, czułośc, wskaźnik F1 dla wyników pozytywnych i negatywnych.
# Im dany wskaźnik jest lepszy -bliższy jedności -tym komórka jest bardziej czerwona
from yellowbrick.classifier import (ClassificationReport,)
fig, ax = plt.subplots (figsize=(6, 3))
cm_viz = ClassificationReport( rfc_over2,classes=["SŁABE", "DOBRE"], label_encoder=mapping)
cm_viz.score (X_test, y_test)
cm_viz.ax.set (title="Raport klasyfikacyjny drzewa losowego")
xlabels = ("Precyzja", "Czułość", "F1")
ax.set_xticks (np.arange(len(xlabels)) + 0.5)
ax.set_xticklabels (xlabels, rotation=45)
ax.set_yticks (np.arange(len(cm_viz.classes)) + 0.5)
ax.set_yticklabels (cm_viz.classes)
las_po_oversamplingu()
# Ważność cech
import pandas as pd
feature_imp = pd.Series(rfc_over2.feature_importances_, index=df.columns[:6]).sort_values(ascending=False)
feature_imp
alcohol 0.284751 sulphates 0.202240 volatile acidity 0.147811 total sulfur dioxide 0.134071 citric acid 0.122991 density 0.108136 dtype: float64
%matplotlib inline
import seaborn as sns
def waznosc_Cech_las_po_ovesamplingu():
sns.barplot(x=feature_imp, y=feature_imp.index)
plt.xlabel('Feature Importance Score')
plt.ylabel('Features')
plt.title("Visualizing Important Features")
#plt.legend()
plt.show()
waznosc_Cech_las_po_ovesamplingu()
cv_results_over=cross_val_score(rfc_over2,X_res2,y_res2,cv=5,scoring="recall")
print(cv_results_over)
[0.81410256 0.96178344 0.89171975 0.94267516 0.94267516]
def wykres_blad_prognozowania_klas_las():
from yellowbrick.classifier import (ClassPredictionError,)
fig, ax = plt.subplots (figsize=(6, 3))
cpe_viz = ClassPredictionError(rfc_over2, classes=["Słabsze", "Lepsze"])
cpe_viz.score (X_test, y_test)
ax.set_xticks (np.arange(len(cpe_viz.classes)))
ax.set_xticklabels (cpe_viz.classes)
ax.set(title="Błąd prognozowania klas dla klasyfikatora lasu losowego", xlabel="Klasa rzeczywista", ylabel="Klasa prognozowana")
wykres_blad_prognozowania_klas()
RocCurveDisplay.from_estimator(rfc_over2, X_test, y_test);
def wykres_analiza_lime_las():
# Analiza LIME pokazująca, jak poszczególne cechy próbki przesuwają wyniki prognozy w prawo (wybór lepszego gatunku) lub w lewo (słabego gatunku)
# Poniżej przedstawiony jest kod umożliwiający interpretację ostatniej próbki danych ze zbioru treningowego, dla której nasz model drzewa decyzyjnego prognozuje wybór lepszego gatunku:
from lime import lime_tabular
explainer = lime_tabular. LimeTabularExplainer(X_res2.values, feature_names=X.columns, class_names=["słabsze", "lepsze"])
exp = explainer.explain_instance( X_res2.iloc[-1].values, rfc_over2.predict_proba)
# Danymi wejściowymi dla pakietu LIME nie może być struktura DataFrame. Zwróć uwagę, że jest ona zamieniana na tablicę numpy za pomocą atrybutu .values.
fig = exp.as_pyplot_figure()
fig.tight_layout()
fig.gca().set (title="Lokalna interpretacja klasy '%s'" % exp.class_names [1])
wykres_analiza_lime_las()
y_pred_proba = rfc_over2.predict_proba(X_test)[:,1]
recall = []
x = np.arange(0,1, 0.05)
for i in x:
decisions = (y_pred_proba >= i).astype(int)
recall.append([i, recall_score(y_test, decisions)])
recall
[[0.0, 1.0], [0.05, 1.0], [0.1, 1.0], [0.15000000000000002, 0.9523809523809523], [0.2, 0.9285714285714286], [0.25, 0.9047619047619048], [0.30000000000000004, 0.8809523809523809], [0.35000000000000003, 0.8571428571428571], [0.4, 0.7857142857142857], [0.45, 0.7857142857142857], [0.5, 0.7857142857142857], [0.55, 0.7857142857142857], [0.6000000000000001, 0.7619047619047619], [0.65, 0.7380952380952381], [0.7000000000000001, 0.6904761904761905], [0.75, 0.5952380952380952], [0.8, 0.5238095238095238], [0.8500000000000001, 0.38095238095238093], [0.9, 0.30952380952380953], [0.9500000000000001, 0.14285714285714285]]
# Wpływ poziomu cut-off na recall.
cut_off = []
acc = []
for k in recall:
cut_off.append(k[0])
acc.append(k[1])
x = np.arange(0.05,1, 0.05)
for i in x:
decisions = (y_pred_proba >= i).astype(int)
print('Cut-off:', np.round(i,decimals=2), '||','Recall:', np.round(recall_score(y_test, decisions), decimals=5))
print('='*30)
Cut-off: 0.05 || Recall: 1.0 ============================== Cut-off: 0.1 || Recall: 1.0 ============================== Cut-off: 0.15 || Recall: 0.95238 ============================== Cut-off: 0.2 || Recall: 0.92857 ============================== Cut-off: 0.25 || Recall: 0.90476 ============================== Cut-off: 0.3 || Recall: 0.88095 ============================== Cut-off: 0.35 || Recall: 0.85714 ============================== Cut-off: 0.4 || Recall: 0.78571 ============================== Cut-off: 0.45 || Recall: 0.78571 ============================== Cut-off: 0.5 || Recall: 0.78571 ============================== Cut-off: 0.55 || Recall: 0.78571 ============================== Cut-off: 0.6 || Recall: 0.7619 ============================== Cut-off: 0.65 || Recall: 0.69048 ============================== Cut-off: 0.7 || Recall: 0.69048 ============================== Cut-off: 0.75 || Recall: 0.59524 ============================== Cut-off: 0.8 || Recall: 0.52381 ============================== Cut-off: 0.85 || Recall: 0.38095 ============================== Cut-off: 0.9 || Recall: 0.28571 ============================== Cut-off: 0.95 || Recall: 0.14286 ==============================
params={'criterion': ['gini','entropy'],
'n_estimators': [100,200,50,20],
'max_depth': [2,4,5,10,None],
'min_samples_leaf': [1, 2, 3, 4, 5, 10, 20, 25],
'max_features':['sqrt','log2',None]
}
grid_search_over = GridSearchCV(rfc_over2, param_grid=params, cv=5, scoring='recall', n_jobs=-1,verbose=1)
grid_search_over.fit(X_res2, y_res2)
Fitting 5 folds for each of 960 candidates, totalling 4800 fits
GridSearchCV(cv=5, estimator=RandomForestClassifier(random_state=42), n_jobs=-1,
param_grid={'criterion': ['gini', 'entropy'],
'max_depth': [2, 4, 5, 10, None],
'max_features': ['sqrt', 'log2', None],
'min_samples_leaf': [1, 2, 3, 4, 5, 10, 20, 25],
'n_estimators': [100, 200, 50, 20]},
scoring='recall', verbose=1)In a Jupyter environment, please rerun this cell to show the HTML representation or trust the notebook. GridSearchCV(cv=5, estimator=RandomForestClassifier(random_state=42), n_jobs=-1,
param_grid={'criterion': ['gini', 'entropy'],
'max_depth': [2, 4, 5, 10, None],
'max_features': ['sqrt', 'log2', None],
'min_samples_leaf': [1, 2, 3, 4, 5, 10, 20, 25],
'n_estimators': [100, 200, 50, 20]},
scoring='recall', verbose=1)RandomForestClassifier(random_state=42)
RandomForestClassifier(random_state=42)
print(grid_search_over.best_score_)
print(grid_search_over.score(X = X_test, y = y_test))
print(grid_search_over.best_params_)
0.9233382328923729
0.7857142857142857
{'criterion': 'entropy', 'max_depth': 10, 'max_features': None, 'min_samples_leaf': 1, 'n_estimators': 50}
xgb_model = xgb.XGBClassifier(n_estimators=100, random_state=42, max_depth=5, use_label_encoder=False, eval_metric='error')
xgb_model.fit(X_train, y_train)
xgb_model.score (X_test, y_test)
0.9177631578947368
xgb_model.predict_proba (X.iloc[[0]])
array([[9.999390e-01, 6.098256e-05]], dtype=float32)
# Walidacja
xgb_model_cv_results = cross_val_score(xgb_model,X, y,cv=5) #ilokrotność walidacji cv(razy: trening na 4, testowanie na jednej | dzięki wielu podziałom można zobczyć jak radzi sobie z danymi
print(f'Scores: {np.round(xgb_model_cv_results,3)}')
Scores: [0.895 0.838 0.884 0.851 0.865]
print(f'Scores mean: {np.round(np.mean(xgb_model_cv_results),3)}') #liczę średnią ze scorów z kroswalidacji, wynik zbliżony z wynikiem score
Scores mean: 0.867
xgb_model.score( X_test,y_test)
0.9177631578947368
# Poniżej przedstawiony jest kod wizualizujący ważności cech Giniego (dzięki nim można zmniejszyć błąd modelu):
for col, val in sorted(zip (X.columns, xgb_model.feature_importances_),
key=lambda x: x[1], reverse=True,
)[:5]:
print(f" {col:10} {val: 10.3f}")
alcohol 0.290 sulphates 0.210 total sulfur dioxide 0.136 volatile acidity 0.131 citric acid 0.120
# Wykres ważności cech w odniesieniu do największej bezwzględnej wartości współczynnika regresji. Użyta do tej funkcja wizualizuj sama argument relative= True który powoduje że największej wartość jest przypisywana liczba
# 100 lub minus 100 a pozostałem wartością proporcjonalnie mniejsze liczby.
from yellowbrick.model_selection import FeatureImportances
def wykres_waznosci_Cech_XGBoost():
fig, ax = plt.subplots (figsize=(6, 4))
fi_viz = FeatureImportances (xgb_model)
fi_viz.fit(X, y)
fi_viz.ax.set(title="Ważność 6 cech (XGBoost)", xlabel = "Względna ważność")
wykres_waznosci_Cech_XGBoost()
from sklearn.metrics import accuracy_score
xgb_model_prediction_tr = xgb_model.predict(X_train)
xgb_model_prediction_ts = xgb_model.predict(X_test)
print(sklearn.metrics.classification_report(y_test, prediction_ts, target_names=["słabe", "dobre"]))
precision recall f1-score support
słabe 0.94 0.94 0.94 262
dobre 0.60 0.60 0.60 42
accuracy 0.89 304
macro avg 0.77 0.77 0.77 304
weighted avg 0.89 0.89 0.89 304
print('accuracy train data is',accuracy_score(y_train,xgb_model_prediction_tr))
print('accuracy test data is',accuracy_score(y_test,xgb_model_prediction_ts))
accuracy train data is 1.0 accuracy test data is 0.9177631578947368
print('recall train data is',recall_score(y_train,xgb_model_prediction_tr,average="macro"))
print('recall test data is',recall_score(y_test,xgb_model_prediction_ts,average="macro"))
recall train data is 1.0 recall test data is 0.8123409669211196
# get confusion matrix
xgb_model_predictions = xgb_model.predict(X_test)
xgb_model_matrix = sklearn.metrics.confusion_matrix(y_test, xgb_model_predictions)
xgb_model_matrix
array([[251, 11],
[ 14, 28]], dtype=int64)
sklearn.metrics.f1_score(y_test, xgb_model_predictions, average="micro")
0.9177631578947368
from yellowbrick.classifier import (ConfusionMatrix,)
mapping = {0: "Słabe", 1: "Dobre"}
fig, ax = plt.subplots (figsize=(6, 6))
cm_viz = ConfusionMatrix(xgb_model,classes=["Słabe", "Dobre"], label_encoder=mapping,)
cm_viz.score (X_test, y_test)
cm_viz.ax.set(title="Tablica pomyłek klasyfikatora XGBoost ", xlabel="Klasa prognozowana", ylabel="Klasa rzeczywista")
# Ćwiartki lewa górna i prawa dolna zawierają poprawne wyniki klasyfikacji, a lewa dolna i prawa górna -błędne; ćwiartka lewa dolna zawiera wyniki fałszywie negatywne
# a prawa górna - fałszywie pozytywne. Centrum dobrego klasyfikatora są duże wartości prawdziwych wyników na przekątnej tabeli
[Text(0.5, 1.0, 'Tablica pomyłek klasyfikatora XGBoost '), Text(0.5, 0, 'Klasa prognozowana'), Text(0, 0.5, 'Klasa rzeczywista')]
def raport_XGBoost():
# Raport klasyfikacyjny prezentujący precyzję, czułośc, wskaźnik F1 dla wyników pozytywnych i negatywnych.
# Im dany wskaźnik jest lepszy -bliższy jedności -tym komórka jest bardziej czerwona
from yellowbrick.classifier import (ClassificationReport,)
fig, ax = plt.subplots (figsize=(6, 3))
xgb_model_cm_viz = ClassificationReport( xgb_model,classes=["SŁABE", "DOBRE"], label_encoder=mapping)
xgb_model_cm_viz.score (X_test, y_test)
xgb_model_cm_viz.ax.set (title="Raport klasyfikacyjny drzewa losowego")
xlabels = ("Precyzja", "Czułość", "F1")
ax.set_xticks (np.arange(len(xlabels)) + 0.5)
ax.set_xticklabels (xlabels, rotation=45)
ax.set_yticks (np.arange(len(xgb_model_cm_viz.classes)) + 0.5)
ax.set_yticklabels (xgb_model_cm_viz.classes)
raport_XGBoost()
def prezycja_czulosc_xgboost():
from yellowbrick.classifier import ( PrecisionRecallCurve,)
fig, ax = plt.subplots (figsize=(6, 4))
xgb_model_viz = PrecisionRecallCurve (xgb.XGBClassifier(n_estimators=100, random_state=42, max_depth=5, use_label_encoder=False, eval_metric='error'))
xgb_model_viz. fit (X_train, y_train)
print(xgb_model_viz.score (X_test, y_test))
xgb_model_viz.ax.set(title="Krzywa precyzja-czułość klasyfikatora",xlabel="Czułość", ylabel="Precyzja")
ax.legend (("Binarna krzywa precyzja-czułość","Średnia precyzja = {:0.2f}".format (xgb_model_viz.score(X_test,y_test))),frameon=True, loc="lower left")
prezycja_czulosc_xgboost()
0.7624161858790544
def rownowaga_klas_xgboost():
from yellowbrick.classifier import ClassBalance
fig, ax = plt.subplots (figsize=(6,6))
xgb_model_cb_viz=ClassBalance (labels =["Słabsze", "Lepsze"])
xgb_model_cb_viz.fit(y_test)
ax.set_xticks (np.arange(len(xgb_model_cb_viz.labels)))
ax.set_xticklabels (xgb_model_cb_viz.labels)
ax.set(title="Równowaga klas dla (:,) próbek".format(xgb_model_cb_viz.support_.sum()), ylabel="Liczba próbek")
rownowaga_klas_xgboost()
def wykres_blad_prognozaowania_klas_XGboost():
# Błąd prognozowania klas
# wykres błędu prognozowania klas ilustrujący tablicę pomyłek.
from yellowbrick.classifier import (ClassPredictionError,)
fig, ax = plt.subplots (figsize=(6, 3))
xgb_model_cpe_viz = ClassPredictionError(xgb_model, classes=["Słabsze", "Lepsze"])
xgb_model_cpe_viz.score (X_test, y_test)
ax.set_xticks (np.arange(len(xgb_model_cpe_viz.classes)))
ax.set_xticklabels (xgb_model_cpe_viz.classes)
ax.set(title="Błąd prognozowania klas dla klasyfikatora drzewa losowego", xlabel="Klasa rzeczywista", ylabel="Klasa prognozowana")
wykres_blad_prognozaowania_klas_XGboost()
def wykres_lime_xgboost():
from lime import lime_tabular
xgb_model_explainer = lime_tabular. LimeTabularExplainer(X_train.values, feature_names=X.columns, class_names=["słabsze", "lepsze"])
xgb_model_exp = xgb_model_explainer.explain_instance( X_train.iloc[-1].values, xgb_model.predict_proba)
xgb_model_fig = xgb_model_exp.as_pyplot_figure()
xgb_model_fig.tight_layout()
xgb_model_fig.gca().set (title="Lokalna interpretacja klasy '%s'" % xgb_model_exp.class_names [1])
wykres_lime_xgboost()
xgb_model_ypred = xgb_model.predict(X_test)
xgb_model_ypred
roc_auc_score(y_test, xgb_model_ypred)
0.8123409669211196
plot_roc_curve(xgb_model, X_test, y_test)
<sklearn.metrics._plot.roc_curve.RocCurveDisplay at 0x2516b8d1f00>
def wykres_nieliniowy_Zwiazek_XgBoost():
xgb_reg_model_X_sul=df[['sulphates']].values
xgb_reg_model_y_q=df['alcohol'].values
xgb_reg_model = xgb.XGBRegressor(random_state=123, n_estimators=5, max_depth=7)
xgb_reg_model.fit(xgb_reg_model_X_sul, xgb_reg_model_y_q)
xgb_reg_model_sort_idx= xgb_reg_model_X_sul. flatten().argsort()
lin_regplot (xgb_reg_model_X_sul[xgb_reg_model_sort_idx], xgb_reg_model_y_q[xgb_reg_model_sort_idx], xgb_reg_model)
plt.xlabel('Nieliniowy związek zmiennych [sulphates i alkohol]-trend kształtujący dane')
plt.ylabel('Zawartość alkoholu')
wykres_nieliniowy_Zwiazek_XgBoost()
get_ipython().run_line_magic('matplotlib', 'inline')
import seaborn as sns
from matplotlib import style
import warnings
warnings.filterwarnings('ignore')
from sklearn.cluster import KMeans
from sklearn.metrics import silhouette_score
from sklearn.decomposition import PCA
wine_df = df.drop('quality', axis=1)
wine_df.columns
Index(['volatile acidity', 'citric acid', 'total sulfur dioxide', 'density',
'sulphates', 'alcohol'],
dtype='object')
wss=[] # poszukiwanie ilości klastrów
for i in range(1,10):
kmeans = KMeans(n_clusters=i, init='k-means++', random_state=42)
kmeans.fit(wine_df)
wss.append(kmeans.inertia_)
plt.plot(range(1,10), wss)
plt.title('The Elbow method')
plt.xlabel('Number of clusters')
plt.ylabel('Sum of squared distances')
plt.show()
from yellowbrick.cluster import KElbowVisualizer # potwierdzenie rezultatu wyboru ilości klastrów
model = KMeans()
visualizer = KElbowVisualizer(model, k=(1,10), timings = False)
visualizer.fit(wine_df)
visualizer.show()
<AxesSubplot:title={'center':'Distortion Score Elbow for KMeans Clustering'}, xlabel='k', ylabel='distortion score'>
for i in range(2,10): # poszukiwanie ilości klastrów metodą silhoutte
kmeans = KMeans(n_clusters=i, max_iter=100)
kmeans.fit(wine_df)
score = silhouette_score(wine_df, kmeans.labels_)
print("For cluster: {}, the silhouette score is: {}".format(i,score))
For cluster: 2, the silhouette score is: 0.6480985477659772 For cluster: 3, the silhouette score is: 0.5922607634646007 For cluster: 4, the silhouette score is: 0.5679248263856477 For cluster: 5, the silhouette score is: 0.5619430259857251 For cluster: 6, the silhouette score is: 0.5387907987375498 For cluster: 7, the silhouette score is: 0.5233483273544406 For cluster: 8, the silhouette score is: 0.5242946721400978 For cluster: 9, the silhouette score is: 0.5190743734255969
silhouette_coefficients = []
for i in range(2,10):
kmeans = KMeans(n_clusters=i, max_iter=100)
kmeans.fit(wine_df)
score = silhouette_score(wine_df, kmeans.labels_)
silhouette_coefficients.append(score)
plt.plot(range(2,10), silhouette_coefficients)
plt.xticks(range(2,10))
plt.xlabel("number of clusters")
plt.ylabel("Silhouette coefficient")
plt.show()
pca = PCA()
X = pca.fit_transform(wine_df)
kmeans = KMeans(n_clusters=3)
label = kmeans.fit_predict(X)
unique_labels = np.unique(label)
for i in unique_labels:
plt.scatter(X[label==i,0], X[label==i,1], label=i, s=20)
plt.legend()
plt.title('wine groups')
plt.show
<function matplotlib.pyplot.show(close=None, block=None)>
Wszystkie modele zostały przetestowane cross_val_score, natomiast parametry zostały wybrane za pomocą GridSearchCV.
Metryką, która była dla nas najbardziej istotna jest Recall, która jest intuicyjnie zdolnością klasyfikatora do znalezienia wszystkich pozytywnych próbek.
Poniżej tabelka z porównaniem metryk dla modeli.
def compare_models():
compare_models=pd.DataFrame({"Model":["Regresja logistyczna","Drzewo decyzyjne","Las losowy","Las losowy po oversamplingu","XGBoost" ],
"Recall":[recall_score(y_test, pred_test),recall_score(y_test,prediction_ts),recall_score(y_test, yPred_test),recall_score(y_test, yPred_over2),recall_score(y_test,xgb_model_prediction_ts)],
"F1":[f1_score(y_test, pred_test),f1_score(y_test,prediction_ts),f1_score(y_test, yPred_test),f1_score(y_test, yPred_over2),f1_score(y_test,xgb_model_prediction_ts)],
"Precision":[precision_score(y_test, pred_test),precision_score(y_test,prediction_ts),precision_score(y_test, yPred_test),precision_score(y_test, yPred_over2),precision_score(y_test,xgb_model_prediction_ts)]
})
return compare_models
compare_models()
| Model | Recall | F1 | Precision | |
|---|---|---|---|---|
| 0 | Regresja logistyczna | 0.595238 | 0.632911 | 0.675676 |
| 1 | Drzewo decyzyjne | 0.595238 | 0.595238 | 0.595238 |
| 2 | Las losowy | 0.642857 | 0.675000 | 0.710526 |
| 3 | Las losowy po oversamplingu | 0.785714 | 0.653465 | 0.559322 |
| 4 | XGBoost | 0.666667 | 0.691358 | 0.717949 |
# zdefiniowanie walidacji
from sklearn.model_selection import StratifiedKFold
skf = StratifiedKFold(n_splits=4, shuffle=True, random_state=42)
models = [model_LR, dt, rfc,xgb_model]
def run_model(model, X, y, cross_val):
"""
funkcja przeprowadzająca trening na liście modeli
input:
model: model estymatora z pakietu sklearn
X: cechy do przeprowadzenia uczenia
y: target
cross_val: rodzaj walidacji
output/print:
fbeta_res: wynik fbeta na każdy fold / później uśredniony
accuracy_res: wynik accuracy na każdy fold / później uśredniony
cross_val_time: total scoring time dla obu metryk
"""
model_name = type(model).__name__
fbeta_scorer = make_scorer(fbeta_score, beta=0.5)
start = time()
fbeta_res = cross_val_score(model, X, y, cv=cross_val, scoring=fbeta_scorer)
accuracy_res = cross_val_score(model, X, y, cv=cross_val, scoring='accuracy')
end = time()
cross_val_time = end-start
print("{} fbeta: {:.4f}, accuracy: {:.4f}, time: {}".format(model_name, np.mean(fbeta_res), np.mean(accuracy_res), cross_val_time))
# ewaluacja modeli
for model in models:
run_model(model, X_train, y_train, skf)
LogisticRegression fbeta: 0.4535, accuracy: 0.8762, time: 0.27028656005859375 DecisionTreeClassifier fbeta: 0.5188, accuracy: 0.8729, time: 0.059844970703125 RandomForestClassifier fbeta: 0.6261, accuracy: 0.8985, time: 1.716792106628418 XGBClassifier fbeta: 0.5824, accuracy: 0.8870, time: 0.7689893245697021
# fit models
for model in models:
model.fit(X_train, y_train)
# wyniki predykcji
y_pred_LR_model = model_LR.predict(X_test)
y_pred_DT_model = dt.predict(X_test)
y_pred_RF_model = rfc.predict(X_test)
y_pred_XGB_model = xgb_model.predict(X_test)
y_pred_LR_model,y_pred_DT_model,y_pred_RF_model,y_pred_XGB_model
(array([0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0,
1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
0, 0, 1, 0, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0,
1, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1,
0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0]),
array([0, 1, 1, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0,
1, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,
0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1,
0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0,
0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1,
0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0]),
array([0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0,
1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0,
1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1,
1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0]),
array([0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0,
1, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0,
1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1,
1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0]))
# sprawdzenie fbeta_score dla każdego modelu między wynikami predykcji
# a rzeczywistymi wartościami ze zbioru treningowego
fbeta_LR = fbeta_score(y_test, y_pred_LR_model, beta=0.5)
fbeta_DT = fbeta_score(y_test, y_pred_DT_model, beta=0.5)
fbeta_RF = fbeta_score(y_test, y_pred_RF_model, beta=0.5)
fbeta_XGB = fbeta_score(y_test, y_pred_XGB_model, beta=0.5)
results = [fbeta_LR, fbeta_DT, fbeta_RF]
fbeta_LR, fbeta_DT, fbeta_RF
(0.6172839506172839, 0.5952380952380952, 0.6958762886597938)
print("-----Wyniki f-beta na zbiorze testowym-----")
print("Logistic Regression f-beta: {:.4f}".format(fbeta_LR))
print("Decision Tree f-beta: {:.4f}".format(fbeta_DT))
print("RandomForest f-beta: {:.4f}".format(fbeta_RF))
print("XGBoost f-beta: {:.4f}".format(fbeta_XGB))
-----Wyniki f-beta na zbiorze testowym----- Logistic Regression f-beta: 0.6173 Decision Tree f-beta: 0.5952 RandomForest f-beta: 0.6959 XGBoost f-beta: 0.7071
def confusion_matrix_model_the_best():
cf_matrix = confusion_matrix(y_true=y_test, y_pred=y_pred_XGB_model)
group_names = ['True Neg','False Pos','False Neg','True Pos']
group_counts = ['{0:0.0f}'.format(value) for value in cf_matrix.flatten()] #flatten() 'splaszcza' matryce
labels = [f'{v1}\n{v2}' for v1, v2 in zip(group_names,group_counts)]
labels = np.asarray(labels).reshape(2,2)
sns.set(rc={'figure.figsize':(8,6)})
ax = sns.heatmap(cf_matrix, annot=labels, fmt='', cmap='Blues')
ax.set(xlabel='Predicted', ylabel='Actual');
confusion_matrix_model_the_best()
def wykres_ROC_all():
#set up plotting area
plt.figure(0).clf()
from matplotlib.pyplot import figure
figure(figsize=(12, 12), dpi=80)
#fit logistic regression model and plot ROC curve
# model = LogisticRegression()
pred_test# = model.predict_proba(X_test)[:, 1]
fpr, tpr, _ = metrics.roc_curve(y_test, pred_test)
auc = round(metrics.roc_auc_score(y_test, pred_test), 4)
plt.plot(fpr,tpr,label="Logistic Regression, AUC="+str(auc))
#fit gradient boosted model and plot ROC curve
#model = GradientBoostingClassifier()
#model.fit(X_train, y_train)
#y_pred = model.predict_proba(X_test)[:, 1]
fpr, tpr, _ = metrics.roc_curve(y_test, xgb_model_prediction_ts)
auc = round(metrics.roc_auc_score(y_test, xgb_model_prediction_ts), 4)
plt.plot(fpr,tpr,label="Gradient Boosting, AUC="+str(auc))
#fit Decision Tree model and plot ROC curve
# model = DecisionTreeClassifier()
# model.fit(X_train, y_train)
prediction_ts# = model.predict_proba(X_test)[:, 1]
fpr, tpr, _ = metrics.roc_curve(y_test, prediction_ts)
auc = round(metrics.roc_auc_score(y_test, prediction_ts), 4)
plt.plot(fpr,tpr,label="DecisionTree, AUC="+str(auc))
#fit random forest model and plot ROC curve
# model = RandomForestClassifier()
# model.fit(X_train, y_train)
yPred_test# = model.predict_proba(X_test)[:, 1]
fpr, tpr, _ = metrics.roc_curve(y_test, yPred_test)
auc = round(metrics.roc_auc_score(y_test, yPred_test), 4)
plt.plot(fpr,tpr,label="RandomForest, AUC="+str(auc))
#add legend
plt.legend()
wykres_ROC_all();
<Figure size 576x432 with 0 Axes>
def wykres_porownanie_waznosci_cech():
from yellowbrick.model_selection import FeatureImportances
plt.figure(figsize=(15,8))
feats = get_quant_features(wine)
# lewy wykres
plt.subplot(2, 2, 1)
fi_viz = FeatureImportances(dt, labels=feats)
fi_viz.fit(X, y)
fi_viz.ax.set(title="Drzewo decyzyjne")
# prawy wykres
plt.subplot(2, 2, 2)
fi_viz1 = FeatureImportances (rfc, labels=feats)
fi_viz1.fit(X, y)
fi_viz1.ax.set(title="Las losowy")
plt.subplot(2, 2, 3)
fi_viz = FeatureImportances(xgb_model, labels=feats)
fi_viz.fit(X, y)
fi_viz.ax.set(title="XGBoost")
plt.suptitle('Ważność 6 cech');
wykres_porownanie_waznosci_cech()
def waznosc_RF():
feature_imp_RF = pd.Series(rfc.feature_importances_, index=df.columns[:6]).sort_values(ascending=False)
feature_imp_DT = pd.Series(dt.feature_importances_, index=df.columns[:6]).sort_values(ascending=False)
feature_imp_XG = pd.Series(xgb_model.feature_importances_, index=df.columns[:6]).sort_values(ascending=False)
import seaborn as sns
plt.subplot(2, 2, 1)
sns.barplot(x=feature_imp_DT, y=feature_imp_DT.index)
#plt.xlabel('Ważność cech - drzewo decyzyjne ')
#plt.ylabel('Features')
plt.title("Ważność cech - drzewo decyzyjne")
plt.show()
plt.subplot(2, 2, 2)
sns.barplot(x=feature_imp_RF, y=feature_imp_RF.index)
#plt.xlabel('Feature Importance Score')
#plt.ylabel('Features')
plt.title("Ważność cech - las losowy")
plt.show()
plt.subplot(2, 2, 3)
sns.barplot(x=feature_imp_XG, y=feature_imp_XG.index)
#plt.xlabel('Feature Importance Score')
#plt.ylabel('Features')
plt.title("Ważność cech - XGBoost")
plt.show()
waznosc_RF()
import xgboost as xgb
#xgb_model = xgb.XGBClassifier(n_estimators=100, random_state=42, max_depth=5, use_label_encoder=False, eval_metric='error')
xgr = xgb.XGBRegressor(random_state=42, base_score=0.5,max_depth=5, use_label_encoder=False, eval_metric='error')
xgr.fit(X_train,y_train)
XGBRegressor(base_score=0.5, booster='gbtree', callbacks=None,
colsample_bylevel=1, colsample_bynode=1, colsample_bytree=1,
early_stopping_rounds=None, enable_categorical=False,
eval_metric='error', gamma=0, gpu_id=-1, grow_policy='depthwise',
importance_type=None, interaction_constraints='',
learning_rate=0.300000012, max_bin=256, max_cat_to_onehot=4,
max_delta_step=0, max_depth=5, max_leaves=0, min_child_weight=1,
missing=nan, monotone_constraints='()', n_estimators=100, n_jobs=0,
num_parallel_tree=1, predictor='auto', random_state=42,
reg_alpha=0, reg_lambda=1, ...)In a Jupyter environment, please rerun this cell to show the HTML representation or trust the notebook. XGBRegressor(base_score=0.5, booster='gbtree', callbacks=None,
colsample_bylevel=1, colsample_bynode=1, colsample_bytree=1,
early_stopping_rounds=None, enable_categorical=False,
eval_metric='error', gamma=0, gpu_id=-1, grow_policy='depthwise',
importance_type=None, interaction_constraints='',
learning_rate=0.300000012, max_bin=256, max_cat_to_onehot=4,
max_delta_step=0, max_depth=5, max_leaves=0, min_child_weight=1,
missing=nan, monotone_constraints='()', n_estimators=100, n_jobs=0,
num_parallel_tree=1, predictor='auto', random_state=42,
reg_alpha=0, reg_lambda=1, ...)# Shapley- Daje ona ogólny wgląd w model i ułatwia interpretację poszczególnych prognoz.
# Sprawdzamy prognozowany wynik dla próbki o indeksie __.
sample_idx =11
xgr.predict (X_train.iloc[[sample_idx]])
array([-0.00321445], dtype=float32)
import shap
shap.initjs()
exp = shap. TreeExplainer (xgr)
vals = exp.shap_values (X_train)
shap.force_plot(exp.expected_value,vals [sample_idx], X_train.iloc[sample_idx],)
#Utworzono obiekt TreeExplainer i wyliczono wartość shap dla próbek.
#Po utworzeniu obiektu w wyliczeniu wartości utworzona wykres siłowy ułatwiające interpretację prognozowanych wartości
# Wykres siłowy opisujący model regresyjny; poszczególne cechy obniżają wartość bazową z __ do ___
# Base Value to prognozowana wartość bazowa, czerwone cechy to te które podnoszą jakość wszystkie to te które obniżają jakość.
# Można również utworzyć wykres siłowy dla wszystkich próbek i uzyskać w ten sposób obraz działania całego modelu.
# Jeżeli w środowisku Jupyter jest włączo na obsługa skryptów JavaScript, po umieszczeniu nad próbką wskaźnika my szy pojawia się informacja o cechach,
# które wpływają na prognozowany wynik. Poniższy kod tworzy interaktywny wykres:
shap.force_plot( exp.expected_value, vals, X_train)